﻿using System;
using System.Linq;
using System.Collections.Generic;
using System.ComponentModel;
using System.Windows;
using SL.MVVMS.RIA;
using System.ServiceModel.DomainServices.Client;
using MVVM_S.Samples.HelpDesk.Web.Models;
using MVVM_S.Samples.HelpDesk.Web.Services;

namespace MVVM_S.Samples.HelpDesk.Services
{
    /// <summary>
    /// A service class should be created for each RIA DomainContext in your project
    /// This class should expose Collections of Data.  Do not add properties, such as SelectedItems
    /// to your service.  Allow your ViewModel to handle these items.
    /// 
    /// Follow the TODO: items in the file to complete the implementation in your project
    /// 
    /// Use the <see cref="slsvccollection">slsvccollection</see> snippet to expose items from your domain context
    /// which should be provided / changed / updated by this service.  For example: a customer list
    /// </summary>
    public class HelpdeskService
    {
        #region Basic Service Implementation

        // This provides management functions for the Project's Domain context
        ContextManager contextManager;

        // DONE: Replace this type with your project's provided DomainContext
        HelpdeskContext domainContext;
        // DONE: Replace this type with your project's provided DesignData Service
        HelpdeskDesign designData;


        public HelpdeskService()
        {
            if (DesignerProperties.IsInDesignTool)
            {
                // DONE: Replace this type with your project's provided DesignData Service
                designData = new HelpdeskDesign();
            }
            else
            {
                // DONE: Replace this type with your project's provided DomainContext
                domainContext = new HelpdeskContext();
                contextManager = new ContextManager(domainContext, OnError);
            }
        }

        void OnError(Exception ex)
        { 
            // DONE: Place your Error Handling Here
            MessageBox.Show(ex.Message, 
                "Helpdesk Sever Error",
                MessageBoxButton.OK);
        }

        #region Standard Items in the Class - Do not change

        /// <summary>
        /// Adds a new Entity to the collection for submitting on the next save
        /// </summary>
        /// <param name="entity"></param>
        public void Add(Entity entity)
        {
            EntitySet es = domainContext.EntityContainer.GetEntitySet(entity.GetType());
            es.Add(entity);
        }

        /// <summary>
        /// Marks an Entity in the collection as deleted, which is submitted on the next save
        /// </summary>
        /// <param name="entity"></param>
        public void Delete(Entity entity)
        {
            EntitySet es = domainContext.EntityContainer.GetEntitySet(entity.GetType());
            es.Remove(entity);
        }

        /// <summary>
        /// Saves all data currently not persisted
        /// </summary>
        /// <param name="done"></param>
        public void Save(Action done)
        {
            contextManager.SaveData(done);
        }

        /// <summary>
        /// Reverses all pending changes since the data was loaded
        /// </summary>
        public void Undo()
        {
            domainContext.RejectChanges();
        }

        /// <summary>
        /// Return Status of the DomainContet
        /// </summary>
        public bool IsWorking
        {
            get { return domainContext.IsLoading | domainContext.IsSubmitting; }
        }
        #endregion

        #endregion



        #region Collection Properties
        // DONE: Add collections here using the slsvccollection snippet
                
        public EntitySet<User> Users
        {
            get
            {
                if (domainContext == null)
                    return designData.Users;
                else
                    return domainContext.Users;
            }
        }
        
        public EntitySet<Category> Categories
        {
            get
            {
                if (domainContext == null)
                    return designData.Categories;
                else
                    return domainContext.Categories;
            }
        }
        
        public EntitySet<Note> Notes
        {
            get
            {
                if (domainContext == null)
                    return designData.Notes;
                else
                    return domainContext.Notes;
            }
        }
        
        public EntitySet<Office> Offices
        {
            get
            {
                if (domainContext == null)
                    return designData.Offices;
                else
                    return domainContext.Offices;
            }
        }

        
        public EntitySet<Ticket> Tickets
        {
            get
            {
                if (domainContext == null)
                    return designData.Tickets;
                else
                    return domainContext.Tickets;
            }
        }
                
                
                
                
        #endregion



        // DONE: Add your load methods following the examples provided
        #region Load Data Functions
        /// <summary>
        /// Loads Just the list of Open Tickets
        /// </summary>
        /// <param name="callback">Action to perform after load</param>
        public void LoadOpenTickets(Action callback)
        {
            if (domainContext == null)
            {
                callback();
                return;
            }

            var query = domainContext.GetTicketsQuery()
                .Where(t => t.Resolved == null);
            contextManager.LoadData(query
                , OnLoadComplete: callback   // The callback occurs OnLoadComplete
                , ProcessDeletes: true);
        }

        /// <summary>
        /// Find Tickets for a User
        /// </summary>
        /// <param name="callback">Action to perform after load</param>
        public void LoadTicketsForUser(int userID, Action callback)
        {
            if (domainContext == null)
            {
                callback();
                return;
            }

            var query = domainContext.GetTicketsQuery()
                .Where(t => t.UserID == userID);
            contextManager.LoadData(query
                , OnLoadComplete: callback   // The callback occurs OnLoadComplete
                , ProcessDeletes: true);
        }

        /// <summary>
        /// Find a Ticket based upon search string
        /// </summary>
        /// <param name="search">String to Search For</param>
        /// <param name="callback">Action to perform after load</param>
        public void SearchForTicket(string search, Action callback)
        {
            if (domainContext == null)
            {
                callback();
                return;
            }

            var query = domainContext.GetTicketsQuery()
                .Where(t => t.Title.Contains(search) | t.Details.Contains(search));
            contextManager.LoadData(query
                , OnLoadComplete: callback   // The callback occurs OnLoadComplete
                , ProcessDeletes: true);
        }

        /// <summary>
        /// Loads full details about a ticket (Ticket, and Notes)
        /// </summary>
        /// <param name="callback">Action to perform after load</param>
        public void LoadTicketDetails(int ticketID, Action callback)
        {
            if (domainContext == null)
            {
                callback();
                return;
            }

            // Batch these Queries together
            contextManager.StartBatch(callback);    // The callback occurs with the batch

            // No Callback Needed for LoadData operations, they are completed with Batch
            contextManager.LoadData(domainContext.GetTicketsQuery().Where(t => t.TicketID == ticketID));
            contextManager.LoadData(domainContext.GetNotesQuery().Where(n => n.TicketID == ticketID),
            ProcessDeletes: true);

            // Signifies the End of the Batching Process
            contextManager.EndBatch();
        }

        /// <summary>
        /// Loads all Lookups (Categories, Offices, and Users)
        /// </summary>
        /// <param name="callback">Action to perform after load</param>
        public void LoadLookups(Action callback)
        {
            if (domainContext == null)
            {
                callback();
                return;
            }

            // Batch these Queries together
            contextManager.StartBatch(callback);    // The callback occurs with the batch

            // No Callback Needed for LoadData operations, they are completed with Batch
            contextManager.LoadData(domainContext.GetCategoriesQuery());
            contextManager.LoadData(domainContext.GetOfficesQuery());

            // This example might be better with a filter / query limiter (depending on # of users, etc.)
            contextManager.LoadData(domainContext.GetUsersQuery());

            // Signifies the End of the Batching Process
            contextManager.EndBatch();              
        }
        #endregion

    }
}
